# -*- coding: utf-8 -*-
"""
心理咨询师服务系统 - 管理员模型
"""

from datetime import datetime
from sqlalchemy import Column, Integer, String, Text, Boolean, DateTime, ForeignKey, Enum, Table
from sqlalchemy.orm import relationship
from werkzeug.security import generate_password_hash, check_password_hash
from .base import BaseModel
import enum


class AdminStatus(enum.Enum):
    """管理员状态"""
    ACTIVE = 'active'  # 激活
    INACTIVE = 'inactive'  # 未激活
    SUSPENDED = 'suspended'  # 暂停
    LOCKED = 'locked'  # 锁定


class PermissionType(enum.Enum):
    """权限类型"""
    SYSTEM = 'system'  # 系统权限
    USER = 'user'  # 用户管理
    SCALE = 'scale'  # 量表管理
    ASSESSMENT = 'assessment'  # 测评管理
    CONTENT = 'content'  # 内容管理
    ANALYTICS = 'analytics'  # 数据分析
    FINANCE = 'finance'  # 财务管理
    SETTINGS = 'settings'  # 设置管理


# 管理员权限关联表
admin_permissions = Table(
    'admin_permissions_association',
    BaseModel.metadata,
    Column('admin_id', Integer, ForeignKey('admin_users.id'), primary_key=True),
    Column('permission_id', Integer, ForeignKey('admin_permissions.id'), primary_key=True)
)


class AdminUser(BaseModel):
    """管理员用户"""
    __tablename__ = 'admin_users'
    
    # 基本信息
    username = Column(String(50), nullable=False, unique=True, comment='用户名')
    email = Column(String(100), nullable=False, unique=True, comment='邮箱')
    password_hash = Column(String(255), nullable=False, comment='密码哈希')
    
    # 个人信息
    real_name = Column(String(100), comment='真实姓名')
    phone = Column(String(20), comment='电话号码')
    avatar = Column(String(500), comment='头像URL')
    
    # 状态信息
    status = Column(Enum(AdminStatus), default=AdminStatus.ACTIVE, comment='状态')
    is_super_admin = Column(Boolean, default=False, comment='是否超级管理员')
    
    # 登录信息
    last_login_at = Column(DateTime, comment='最后登录时间')
    last_login_ip = Column(String(45), comment='最后登录IP')
    login_count = Column(Integer, default=0, comment='登录次数')
    
    # 安全设置
    failed_login_attempts = Column(Integer, default=0, comment='失败登录次数')
    locked_until = Column(DateTime, comment='锁定到期时间')
    password_changed_at = Column(DateTime, comment='密码修改时间')
    
    # 两步验证
    two_factor_enabled = Column(Boolean, default=False, comment='是否启用两步验证')
    two_factor_secret = Column(String(100), comment='两步验证密钥')
    
    # 创建者信息
    created_by = Column(Integer, ForeignKey('admin_users.id'), comment='创建者ID')
    
    # 关系
    creator = relationship('AdminUser', remote_side='AdminUser.id', backref='created_admins')
    permissions = relationship('AdminPermission', secondary=admin_permissions, back_populates='admins')
    
    def __repr__(self):
        return f'<AdminUser {self.username}>'
    
    def set_password(self, password):
        """设置密码"""
        self.password_hash = generate_password_hash(password)
        self.password_changed_at = datetime.utcnow()
    
    def check_password(self, password):
        """验证密码"""
        return check_password_hash(self.password_hash, password)
    
    @property
    def is_active(self):
        """是否激活"""
        return self.status == AdminStatus.ACTIVE
    
    @property
    def is_locked(self):
        """是否被锁定"""
        if self.status == AdminStatus.LOCKED:
            return True
        if self.locked_until and datetime.utcnow() < self.locked_until:
            return True
        return False
    
    def lock_account(self, duration_minutes=30):
        """锁定账户"""
        from datetime import timedelta
        self.locked_until = datetime.utcnow() + timedelta(minutes=duration_minutes)
        self.status = AdminStatus.LOCKED
    
    def unlock_account(self):
        """解锁账户"""
        self.locked_until = None
        self.failed_login_attempts = 0
        if self.status == AdminStatus.LOCKED:
            self.status = AdminStatus.ACTIVE
    
    def record_login_attempt(self, success=True, ip_address=None):
        """记录登录尝试"""
        if success:
            self.last_login_at = datetime.utcnow()
            self.last_login_ip = ip_address
            self.login_count += 1
            self.failed_login_attempts = 0
        else:
            self.failed_login_attempts += 1
            # 失败次数过多时锁定账户
            if self.failed_login_attempts >= 5:
                self.lock_account()
    
    def has_permission(self, permission_code):
        """检查是否有指定权限"""
        if self.is_super_admin:
            return True
        return any(p.code == permission_code for p in self.permissions)
    
    def has_any_permission(self, permission_codes):
        """检查是否有任意一个权限"""
        if self.is_super_admin:
            return True
        return any(self.has_permission(code) for code in permission_codes)
    
    def get_permissions_by_type(self, permission_type):
        """获取指定类型的权限"""
        return [p for p in self.permissions if p.permission_type == permission_type]


class AdminPermission(BaseModel):
    """管理员权限"""
    __tablename__ = 'admin_permissions'
    
    # 权限信息
    code = Column(String(100), nullable=False, unique=True, comment='权限代码')
    name = Column(String(200), nullable=False, comment='权限名称')
    description = Column(Text, comment='权限描述')
    
    # 权限分类
    permission_type = Column(Enum(PermissionType), nullable=False, comment='权限类型')
    parent_id = Column(Integer, ForeignKey('admin_permissions.id'), comment='父权限ID')
    
    # 权限设置
    is_active = Column(Boolean, default=True, comment='是否启用')
    is_system = Column(Boolean, default=False, comment='是否系统权限')
    sort_order = Column(Integer, default=0, comment='排序')
    
    # 权限资源
    resource = Column(String(100), comment='资源标识')
    action = Column(String(50), comment='操作类型')
    
    # 关系
    parent = relationship('AdminPermission', remote_side='AdminPermission.id', backref='children')
    admins = relationship('AdminUser', secondary=admin_permissions, back_populates='permissions')
    
    def __repr__(self):
        return f'<AdminPermission {self.code}: {self.name}>'
    
    @property
    def full_code(self):
        """完整权限代码"""
        if self.parent:
            return f'{self.parent.full_code}.{self.code}'
        return self.code
    
    def get_all_children(self):
        """获取所有子权限"""
        children = []
        for child in self.children:
            children.append(child)
            children.extend(child.get_all_children())
        return children
    
    @classmethod
    def create_default_permissions(cls, db_session):
        """创建默认权限"""
        default_permissions = [
            # 系统管理
            {'code': 'system', 'name': '系统管理', 'permission_type': PermissionType.SYSTEM, 'is_system': True},
            {'code': 'system.config', 'name': '系统配置', 'permission_type': PermissionType.SYSTEM, 'parent_code': 'system'},
            {'code': 'system.logs', 'name': '系统日志', 'permission_type': PermissionType.SYSTEM, 'parent_code': 'system'},
            
            # 用户管理
            {'code': 'user', 'name': '用户管理', 'permission_type': PermissionType.USER},
            {'code': 'user.list', 'name': '用户列表', 'permission_type': PermissionType.USER, 'parent_code': 'user'},
            {'code': 'user.create', 'name': '创建用户', 'permission_type': PermissionType.USER, 'parent_code': 'user'},
            {'code': 'user.edit', 'name': '编辑用户', 'permission_type': PermissionType.USER, 'parent_code': 'user'},
            {'code': 'user.delete', 'name': '删除用户', 'permission_type': PermissionType.USER, 'parent_code': 'user'},
            
            # 量表管理
            {'code': 'scale', 'name': '量表管理', 'permission_type': PermissionType.SCALE},
            {'code': 'scale.list', 'name': '量表列表', 'permission_type': PermissionType.SCALE, 'parent_code': 'scale'},
            {'code': 'scale.create', 'name': '创建量表', 'permission_type': PermissionType.SCALE, 'parent_code': 'scale'},
            {'code': 'scale.edit', 'name': '编辑量表', 'permission_type': PermissionType.SCALE, 'parent_code': 'scale'},
            {'code': 'scale.delete', 'name': '删除量表', 'permission_type': PermissionType.SCALE, 'parent_code': 'scale'},
            
            # 测评管理
            {'code': 'assessment', 'name': '测评管理', 'permission_type': PermissionType.ASSESSMENT},
            {'code': 'assessment.list', 'name': '测评列表', 'permission_type': PermissionType.ASSESSMENT, 'parent_code': 'assessment'},
            {'code': 'assessment.view', 'name': '查看测评', 'permission_type': PermissionType.ASSESSMENT, 'parent_code': 'assessment'},
            {'code': 'assessment.export', 'name': '导出测评', 'permission_type': PermissionType.ASSESSMENT, 'parent_code': 'assessment'},
            
            # 数据分析
            {'code': 'analytics', 'name': '数据分析', 'permission_type': PermissionType.ANALYTICS},
            {'code': 'analytics.dashboard', 'name': '数据面板', 'permission_type': PermissionType.ANALYTICS, 'parent_code': 'analytics'},
            {'code': 'analytics.reports', 'name': '分析报告', 'permission_type': PermissionType.ANALYTICS, 'parent_code': 'analytics'},
        ]
        
        # 创建权限映射
        permission_map = {}
        
        # 先创建所有权限
        for perm_data in default_permissions:
            existing = db_session.query(cls).filter_by(code=perm_data['code']).first()
            if not existing:
                permission = cls(
                    code=perm_data['code'],
                    name=perm_data['name'],
                    permission_type=perm_data['permission_type'],
                    is_system=perm_data.get('is_system', False)
                )
                db_session.add(permission)
                permission_map[perm_data['code']] = permission
            else:
                permission_map[perm_data['code']] = existing
        
        db_session.flush()
        
        # 设置父子关系
        for perm_data in default_permissions:
            if 'parent_code' in perm_data:
                permission = permission_map[perm_data['code']]
                parent = permission_map[perm_data['parent_code']]
                permission.parent_id = parent.id
        
        db_session.commit()
        return permission_map